/*
 * array_list.h
 *
 *  Created on: 2012-7-22
 *      Author: lin
 */

#ifndef ARRAY_LIST_H_
#define ARRAY_LIST_H_

#include "def/defs.h"
#include "zmalloc/zmalloc.h"

#define DEF_ARRAY_LIST_CAPACITY 4

typedef struct {
    mixed_t_dup_fn dup_fn;
    mixed_t_free_fn free_fn;
    mixed_t_match_fn match_fn;

    mixed_t* array;

    int32_t capacity;
    int32_t size;
} array_list_t;

typedef struct {
    array_list_t* list;
    int32_t reverse;
    int32_t idx;
} array_list_iter_t;

array_list_t* array_list_new0(int32_t capacity);

static inline array_list_t* array_list_new(void) {
    return array_list_new0(DEF_ARRAY_LIST_CAPACITY);
}

array_list_t* array_list_clean(array_list_t *list);
array_list_t* array_list_free(array_list_t *list);

array_list_t* array_list_set_capacity(array_list_t* list, int32_t newcapacity);

static inline array_list_t* array_list_trim(array_list_t* list) {
    return array_list_set_capacity(list, list->size);
}
array_list_t* array_list_put(array_list_t *list, const mixed_t val);
array_list_t* array_list_set(array_list_t *list, int32_t idx,
        const mixed_t value);

int32_t array_list_index(const array_list_t *list, const mixed_t match);
mixed_t array_list_get(const array_list_t *list, int32_t idx);
array_list_t* array_list_remove(array_list_t *list, int32_t idx);

array_list_iter_t *array_list_iter_new(const array_list_t *list,
        int32_t reverse);
mixed_t array_list_iter_next(array_list_iter_t *iter, int* hasnext);

static inline void array_list_iter_free(array_list_iter_t *iter) {
    zfree(iter);
}

array_list_t *array_list_dup(const array_list_t *orig);

static inline void array_list_rewind(const array_list_t *list,
        array_list_iter_t *iter, int32_t reverse) {
    iter->list = list;
    iter->reverse = reverse;
    iter->idx = reverse ? list->size - 1 : 0;
}

int32_t array_list_to_array(const array_list_t *list, mixed_t* array,
        int32_t sizeto);

#define array_list_foreach(list,mix)\
    for(int32_t i=0;i<(list)->size && (mix=(list)->array[i],1) ;i++)

#define array_list_size(list) (list)->size
#define array_list_capacity(list) (list)->capacity

#define array_list_dup_fn_set(list,dup) (list)->dup_fn=dup
#define array_list_free_fn_set(list,free) (list)->free_fn=free;
#define array_list_match_fn_set(list,match) (list)->match_fn=match

#define array_list_dup_fn_get(list) (list)->dup_fn
#define array_list_free_fn_get(list) (list)->free_fn
#define array_list_match_fn_get(list) (list)->match_fn
#endif /* ARRAY_LIST_H_ */
